home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-01-03 | 11.3 KB | 350 lines | [TEXT/MPS ] |
- {===========================================================}
- { }
- { Server Event Handler }
- { The server event handler usnit found in the }
- { AppleShare 3.0 Developer's Kit Server Control and Server }
- { Event Handling document. }
- { }
- { by J. Luther, Apple Developer Technical Support }
- { Copyright Apple Computer, Inc. 1992-1994 }
- { All rights reserved }
- { }
- { This unit contains the server event handler, the server }
- { event record processor, and related routines. }
-
- UNIT ServerEventHandler;
-
- {==========================================================}
-
- INTERFACE
-
- USES
- AppleTalk, Processes,
- {$IFC UNDEFINED THINK_Pascal}
- Errors, Memory, Packages,
- {$ENDC}
- ServerControlIntf, ServerEventIntf;
-
- CONST
- { This value indicates how many server events can be }
- { queued for ProcessServerEvents to handle later }
- { If you expect a large number of server events to }
- { come in over a shart amount of time, increase this }
- { number. }
- kNumberServerEvents = 100;
-
- TYPE
- { add required queue element fields to a server event }
- { record so we can use it as an OS queue element }
- SERecQElemPtr = ^SERecQElem;
- SERecQElem = RECORD
- qLink: QElemPtr;
- qType: Integer;
- theSERec: ServerEventRecord;
- END;
-
- { extend the tSEQEntry with a few items we need access }
- { to within the server event handler }
- ExtendedSEQEntryPtr = ^ExtendedSEQEntry;
- ExtendedSEQEntry = RECORD
- theSEQEntry: tSEQEntry; { a server event queue entry }
- freeQ, usedQ: QHdr; { queue headers for server }
- { event record queues }
- seRecArrayPtr: Ptr; { pointer to allocated array }
- { of SERecQElem }
- ourPSN: ProcessSerialNumber; { the application's PSN }
- END;
-
- VAR
- { the global extended tSEQEntry record }
- gExtendedSEQEntry: ExtendedSEQEntry;
-
-
- FUNCTION InstallServerEventHandler: OSErr;
-
- FUNCTION RemoveServerEventHandler: OSErr;
-
- PROCEDURE ProcessServerEvents;
-
-
- {==========================================================}
-
- IMPLEMENTATION
-
- { This function calls SCInstallServerEventProc to install }
- { a server event handler. }
- FUNCTION mySCInstallServerEventProc (theSEHandler: ProcPtr): OSErr;
- VAR
- scPB: SCParamBlockRec;
- BEGIN
- scPB.serverEventPB.scSEQEntryPtr := theSEHandler;
- scPB.serverEventPB.scCode := SCInstallServerEventProc;
-
- mySCInstallServerEventProc := SyncServerDispatch(@scPB);
- END;
-
-
- { This function calls SCRemoveServerEventProc to remove a }
- { server event handler. }
- FUNCTION mySCRemoveServerEventProc (theSEHandler: ProcPtr): OSErr;
- VAR
- scPB: SCParamBlockRec;
- BEGIN
- scPB.serverEventPB.scSEQEntryPtr := theSEHandler;
- scPB.serverEventPB.scCode := SCRemoveServerEventProc;
-
- mySCRemoveServerEventProc := SyncServerDispatch(@scPB);
- END;
-
-
- { TheSrvrEventHandler shows what should be done in a }
- { server event handler and no more: It gets a server }
- { event record from the free queue of application supplied }
- { server event records (or if the freeQ is empty, it gets }
- { the oldest server event record from the usedQ ); it }
- { copies AppleShare's server event record (pointed to by }
- { theSERecPtr) into the application's server event record; }
- { it puts the application's server event record into the }
- { used queue where it can be serviced from the }
- { application's event loop; and then, it calls }
- { WakeUpProcess so the event loop can handle the server }
- { event record in the queue as soon as possible. }
- PROCEDURE TheSrvrEventHandler (theSEQPtr: ExtendedSEQEntryPtr;
- theSERecPtr: ServerEventRecordPtr);
- VAR
- theSERecQElemPtr: SERecQElemPtr;
- BEGIN
- WITH theSEQPtr^ DO
- BEGIN
- IF freeQ.qHead <> NIL THEN
- BEGIN
- { get the server event record out of the freeQ }
- theSERecQElemPtr := SERecQElemPtr(freeQ.qHead);
- IF Dequeue(QElemPtr(theSERecQElemPtr), @freeQ) <> noErr THEN
- ; { do nothing with errors }
- { you'd better not be getting them! }
- END
- ELSE
- BEGIN
- { the freeQ is empty, so get the oldest server }
- { event record out of the usedQ }
- theSERecQElemPtr := SERecQElemPtr(usedQ.qHead);
- IF Dequeue(QElemPtr(theSERecQElemPtr), @usedQ) <> noErr THEN
- ; { do nothing with errors }
- { you'd better not be getting them! }
- END;
-
- { copy the server event record into my server }
- { event record }
- theSERecQElemPtr^.theSERec := theSERecPtr^;
-
- { and enqueue my server event record into }
- { the usedQ }
- Enqueue(QElemPtr(theSERecQElemPtr), @usedQ);
-
- { wake up our process so it can handle the server }
- { event record ASAP }
- IF WakeUpProcess(ourPSN) <> noErr THEN
- ; { do nothing with errors }
- { you'd better not be getting them! }
- END;
- END;
-
-
- { InitSEQEntry initializes the fields of gExtendedSEQEntry }
- { to zero, allocates kNumberServerEvents of SERecQElem and }
- { enqueues them into the free queue of gExtendedSEQEntry, }
- { and gets the applications process serial number and puts }
- { it in gExtendedSEQEntry so the server event handler can }
- { wake up the process. InitSEQEntry returns TRUE if the }
- { array of SERecQElem was allocated. }
- FUNCTION InitSEQEntry: Boolean;
- VAR
- theQElemsPtr: Ptr;
- index: Integer;
- BEGIN
- WITH gExtendedSEQEntry DO
- BEGIN
- { point to server event handler }
- theSEQEntry.SEQentry.CallAddr := @TheSrvrEventHandler;
-
- { initially clear all SEeventFlags }
- theSEQEntry.SEeventFlag := 0;
-
- { and clear all SEwhichAFPFlags }
- theSEQEntry.SEwhichAFPFlag[0] := 0;
- theSEQEntry.SEwhichAFPFlag[1] := 0;
-
- { and clear all SEwhichSCFlags }
- theSEQEntry.SEwhichSCFlag := 0;
-
- { allocate some memory for the server event }
- { records and initialize the buffer queues. }
- seRecArrayPtr := NewPtr(kNumberServerEvents * LongInt(sizeof(SERecQElem)));
- IF seRecArrayPtr <> NIL THEN
- BEGIN
- { initialize the usedQ header }
- usedQ.qFlags := 0;
- usedQ.qHead := NIL;
- usedQ.qTail := NIL;
-
- { initialize the freeQ header }
- freeQ.qFlags := 0;
- freeQ.qHead := NIL;
- freeQ.qTail := NIL;
-
- { the free queue holds all of our server }
- { event records initially, so add the }
- { SERecQElems to the freeQ }
- theQElemsPtr := seRecArrayPtr;
- FOR index := 1 TO kNumberServerEvents DO
- BEGIN
- Enqueue(QElemPtr(theQElemsPtr), @freeQ);
- theQElemsPtr := Ptr(ORD4(theQElemsPtr) + LongInt(sizeof(SERecQElem)));
- END;
-
- InitSEQEntry := TRUE; { everything is OK }
- END
- ELSE
- InitSEQEntry := FALSE; { no memory }
-
- IF GetCurrentProcess(ourPSN) <> noErr THEN
- ; { Get our process serial number }
- END;
- END;
-
-
- { SetSEFlags sets the server event flags of }
- { gExtendedSEQEntry to tell AppleShare's server event }
- { mechanism which server events your application's server }
- { event handler are interested in. You can set the }
- { SE flags either before or after your server event }
- { handler is installed. }
- { IMPORTANT NOTES: }
- { • Your server event handler will be called based on the }
- { current settings of SEeventFlag. Make sure }
- { SEeventFlag is either initialized to zero (meaning }
- { your server event handler is not interested in any }
- { server events) or initialized for the specific server }
- { events your application is interested in before you }
- { install your server event handler. }
- { • If you set the bCSEHAFPInDoRequest or }
- { bCSEHAFPInSendResponse bits in SEeventFlag after your }
- { server event handler is installed, make sure you }
- { initialize the SEwhichAFPFlag bits first. }
- { • If you set the bCSEHServerControlCall bit in }
- { SEeventFlag after your server event handler is }
- { installed, make sure you initialize the SEwhichSCFlag }
- { bits first. }
- PROCEDURE SetSEFlags;
- BEGIN
- WITH gExtendedSEQEntry.theSEQEntry DO
- BEGIN
- { If the bCSEHAFPInDoRequest or }
- { bCSEHAFPInSendResponse bits in SEeventFlag are }
- { going to be set, then indicate what AFP calls }
- { you're interested in. For example: }
- { BSET(theSEQEntry.SEwhichAFPFlag[1], afpOpenFork); }
- { will cause a server event for the afpOpenFork }
- { AFP call. }
- { • add your code here • }
-
- { If the bCSEHServerControlCall bit in SEeventFlag }
- { is going to be set, }
- { then indicate what server control calls you're }
- { interested in. For example: }
- { BSET(theSEQEntry.SEwhichSCFlag, SCSetSetupInfo); }
- { will cause a server event for the SCSetSetupInfo }
- { server control call. }
- { • add your code here • }
-
- { Indicate what server events you'd like to be }
- { notified of by setting bits in the SEeventFlag }
- { longword. For example: }
- { BSET(SEeventFlag, bCSEHVolumePrep); }
- { will cause a server event every time the server }
- { prepares a volume for use with AppleShare. }
- { • add your code here • }
- END;
- END;
-
-
- { ProcessServerEvents should be called every time through }
- { the event loop to see if there are any server event }
- { records to process. If there aren't any, then it exits }
- { immediately. If there are any, then it processes the }
- { server event records in the used queue until none are }
- { left. }
- PROCEDURE ProcessServerEvents;
- VAR
- theSERecQElemPtr: SERecQElemPtr;
- BEGIN
- WITH gExtendedSEQEntry DO
- WHILE usedQ.qHead <> NIL DO
- BEGIN
- { get the server event record out of the usedQ }
- theSERecQElemPtr := SERecQElemPtr(usedQ.qHead);
- IF Dequeue(QElemPtr(theSERecQElemPtr), @usedQ) = noErr THEN
- BEGIN
- WITH theSERecQElemPtr^.theSERec DO
- BEGIN
- { do something useful with the }
- { server event record }
- { • add your code here • }
- END;
- { we're done with the server event }
- { record, so put it back in the freeQ }
- Enqueue(QElemPtr(theSERecQElemPtr), @freeQ);
- END;
- END;
- END;
-
-
- { Your application calls InstallServerEventHandler to }
- { install the server event handler. Change the }
- { InitSEQEntry function where indicated to tell the server }
- { event handler mechanism what server events you're }
- { interested in to begin with. }
- FUNCTION InstallServerEventHandler: OSErr;
- VAR
- err: OSErr;
- BEGIN
- { initialize queues and get server event record buffer }
- IF InitSEQEntry THEN
- BEGIN
- { Set the server event flags in }
- { gExtendedSEQEntry.theSEQEntry }
- SetSEFlags;
-
- { install the server event handler }
- err := mySCInstallServerEventProc(@gExtendedSEQEntry);
-
- IF err <> noErr THEN { SE handler not installed? }
- { Then get rid of memory }
- DisposPtr(gExtendedSEQEntry.seRecArrayPtr);
-
- { return any SCInstallServerEventProc errors }
- InstallServerEventHandler := err;
- END
- ELSE
- { return a memory error }
- InstallServerEventHandler := memFullErr;
- END;
-
-
- { Your application calls RemoveServerEventHandler to }
- { remove the server event handler and dispose of the }
- { memory allocated by InitSEQEntry (which is called by }
- { InstallServerEventHandler). }
- FUNCTION RemoveServerEventHandler: OSErr;
- BEGIN
- { remove the server event handler }
- RemoveServerEventHandler := mySCRemoveServerEventProc(@gExtendedSEQEntry);
-
- { get rid of memory used for the server event records }
- IF gExtendedSEQEntry.seRecArrayPtr <> NIL THEN
- DisposPtr(gExtendedSEQEntry.seRecArrayPtr);
- END;
-
-
- END. { ServerEventHandler unit }